package com.ctshk.rpc.order.airexpress.service;

import com.alibaba.fastjson.JSONObject;
import com.ctshk.common.constant.RedisConstants;
import com.ctshk.common.enums.*;
import com.ctshk.common.enums.Currency;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.common.utils.redis.KeyUtil;
import com.ctshk.rpc.airexpress.dto.AirportExpressInfoDTO;
import com.ctshk.rpc.booking.enums.SupplierReserveTypeEnum;
import com.ctshk.rpc.booking.req.system.airexpress.add.SupplierOrderSystemAirExpressAddReq;
import com.ctshk.rpc.booking.req.system.airexpress.add.SupplierSystemOrderAirExpressAddReq;
import com.ctshk.rpc.booking.req.system.airexpress.add.SupplierSystemOrderAirExpressDetailAddReq;
import com.ctshk.rpc.order.airexpress.dto.mtr.AirportExpressMTRDTO;
import com.ctshk.rpc.order.airexpress.dto.mtr.AirportExpressTicketMTRDTO;
import com.ctshk.rpc.order.airexpress.entity.AirportExpressOrder;
import com.ctshk.rpc.order.airexpress.enums.AirExpressTouristType;
import com.ctshk.rpc.order.airexpress.enums.MTRProfile;
import com.ctshk.rpc.order.airexpress.mapper.AirportExpressOrderMapper;
import com.ctshk.rpc.system.dto.UserDTO;
import com.github.kfcfans.powerjob.client.OhMyClient;
import com.github.kfcfans.powerjob.common.response.ResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 机场快线-港铁订单 服务实现类
 * </p>
 *
 * @author 胡广
 * @since 2021-02-23
 */
@Slf4j
@Component
public class AirportExpressService {
    private static final int MAX_GENERATOR_NUM = 10; // 销售编号最大生成数
    @Autowired
    RedisTemplate<String, Object> redisTemplate;
    @Autowired
    AirportExpressOrderMapper airportExpressOrderMapper;

    @Value("${schedule.config.domain}")
    private String domain;

    @Value("${schedule.config.app-name}")
    private String appName;

    @Value("${schedule.config.password}")
    private String password;

    @Value("${schedule.job-id.order.airexpress}")
    private long jobId;

    /**
     * 生成机场快线销售编号=J+部门代码+员工编号+年后2位+月日4位+3位随机数字
     * redis单机无影响，集群可能导致重复
     * @param userDTO
     * @return
     */
    public String generatorOrderNumber(UserDTO userDTO, LocalDateTime nowLocalDateTime) {
        String key = KeyUtil.genKey(RedisConstants.AIR_EXPRESS_ORDER_NUMBER, String.valueOf(userDTO.getId()));
        String orderNumber = (String) redisTemplate.opsForList().leftPop(key);
        if (orderNumber == null) { // redis中不存在订单编号
            StringBuilder orderNumberSb = new StringBuilder("J");
            orderNumberSb.append(userDTO.getDeptCode()).append(userDTO.getEmployeeNumber()).append(DateUtil.fmt(nowLocalDateTime, "yyMMdd"));
            String prefixNumber = orderNumberSb.toString().toUpperCase();
            String maxOrderNumber = airportExpressOrderMapper.selectMaxNumberByDeptUserNow(prefixNumber);
            int num = 1;
            if (maxOrderNumber != null) { // 当日该用户使用过订单编号
                String suffixNumber = maxOrderNumber.substring(maxOrderNumber.length() - 4, maxOrderNumber.length());// 切割最后3位数
                num = Integer.valueOf(suffixNumber);
            }
            // 生成编号
            int count = 1;
            List<String> objects = new LinkedList<>();
            while (count <= MAX_GENERATOR_NUM) { // 一次生成10个订单编号
                String number = StringUtils.leftPad(String.valueOf(num), 3, "0");
                objects.add(prefixNumber + number);
                count++;
                num++;
            }
            redisTemplate.opsForList().rightPushAll(key, objects.toArray()); // pushAll生成的订单编号
            orderNumber = (String) redisTemplate.opsForList().leftPop(key); // pop一个订单编号出来
        }
        return orderNumber;
    }

    /**
     * 生成收款单号:
     * SKD+年後2位+月日4位+時分秒6位+2位隨機數字
     */
    public String generatorPaymentNumber(LocalDateTime nowLocalDateTime) {
        String dateTime = DateUtil.fmt(nowLocalDateTime, "yyMMddHHmmss");
        String randomNumber = String.valueOf((int) ((Math.random() * 9 + 1) * 10));
        StringBuilder orderNumberSb = new StringBuilder();
        orderNumberSb.append("SKD").append(dateTime).append(randomNumber);
        return orderNumberSb.toString().toUpperCase();
    }

    /**
     * 生成收據號碼：門市編號+員工編號+年後2位月日4位+B+時分秒6位+（S），
     * 例如：XS-C07884-200407-B-110008（S）
     *
     * @param userDTO
     * @return
     */
    public String generatorReceiptNumber(UserDTO userDTO, LocalDateTime nowLocalDateTime) {
        String symbol = "-";
        String employeeNumber = userDTO.getEmployeeNumber();
        String deptCode = userDTO.getDeptCode();
        String date = DateUtil.fmt(nowLocalDateTime, "yyMMdd");
        String time = DateUtil.fmt(nowLocalDateTime, "HHmmss");
        StringBuilder receiptNumberSb = new StringBuilder();
        receiptNumberSb.append("XS").append(symbol).append(deptCode).append(symbol)
                .append(employeeNumber).append(symbol)
                .append(date).append("-B-")
                .append(time).append("（S）");
        return receiptNumberSb.toString().toUpperCase();
    }

    /**
     * 生成查询号码，六位随机数字字符串
     *
     * @return
     */
    public String generatorInquiryNumber() {
        String randomNumber = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        return randomNumber;
    }

    /**
     * 下单完成后调用任务执行如果未付款则超时失效订单操作
     *
     * @param id
     */
    public void startScheduleTask(Long id) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", id);
        // 延迟时间,单位毫秒,1800000L=30分钟后执行
        long delayMS = 1000 * 60 * 30;
        log.info("【机场快线订单-提交订单】提交订单成功，启动定时任务:{},appName:{},time:{}", domain, appName, delayMS);
        try {
            OhMyClient taskClient = new OhMyClient(domain, appName, password);
            ResultDTO<Long> resultTask = taskClient.runJob(jobId, jsonObject.toJSONString(), delayMS);

            if (resultTask.isSuccess()) {
                // 任务执行成功,过期时间*2是防止任务启动时redis数据已过期
                redisTemplate.opsForValue().set(RedisConstants.ORDER_INSTANCELD_KEY + id, resultTask.getData(), delayMS * 2, TimeUnit.MILLISECONDS);
            }
        } catch (Exception e) {
            log.error("【机场快线订单-提交订单】提交订单失败，启动定时任务失败", e);
            throw new BusinessException(SystemError.AIREXPRESS_ORDER_60038);
        }
    }

    public SupplierOrderSystemAirExpressAddReq generatorSupplierBooking(AirportExpressOrder airportExpressOrder, UserDTO chargeUser,
                                                                        AirportExpressMTRDTO airportExpressMTRDTO, AirportExpressInfoDTO airportExpressInfoDTO, LocalDateTime localDateTime) {
        SupplierOrderSystemAirExpressAddReq supplierOrderSystemAirExpressAddReq = new SupplierOrderSystemAirExpressAddReq();
        // 生成供应预订单
        supplierOrderSystemAirExpressAddReq.setDepartmentId(chargeUser.getDeptId()); // 资源所属部门ID
        supplierOrderSystemAirExpressAddReq.setDepartment(chargeUser.getDept());
        supplierOrderSystemAirExpressAddReq.setBusinessType(SystemBusinessType.AIR_EXPRESS.getCode());
        supplierOrderSystemAirExpressAddReq.setReserveTypeId(SupplierReserveTypeEnum.AIR_EXPRESS.getId());
        supplierOrderSystemAirExpressAddReq.setSaleType(SalesMethod.SINGLE_SALE.getCode());
        supplierOrderSystemAirExpressAddReq.setProductType(ProductType.API_PRODUCT.getCode());
        supplierOrderSystemAirExpressAddReq.setSaleNumber(airportExpressOrder.getOrderNumber());
        supplierOrderSystemAirExpressAddReq.setProductNumber(airportExpressInfoDTO.getProductCode());
        supplierOrderSystemAirExpressAddReq.setProductName(airportExpressInfoDTO.getTicketTypeNameCn());
        supplierOrderSystemAirExpressAddReq.setSupplierId(airportExpressInfoDTO.getSupplierId()); // 供应商ID
        supplierOrderSystemAirExpressAddReq.setSupplierOrderType(1); //供应商订单类型
        supplierOrderSystemAirExpressAddReq.setSupplierOrderNumber(airportExpressMTRDTO.getRefNo()); //供应商订单号(第三方单号)
        supplierOrderSystemAirExpressAddReq.setConfirmStatus(SupplierConfirmStatus.CONFIRMED.getCode()); //确认状态
        supplierOrderSystemAirExpressAddReq.setConfirmTime(localDateTime);
        supplierOrderSystemAirExpressAddReq.setCurrencyId(Currency.HKD.getCode()); // 机场快线默认值汇率港币
        supplierOrderSystemAirExpressAddReq.setCurrency(Currency.HKD.getCurrency());
        // 构建供应商预订-机场快线
        SupplierSystemOrderAirExpressAddReq supplierSystemOrderAirExpressAddReq = new SupplierSystemOrderAirExpressAddReq();
        supplierOrderSystemAirExpressAddReq.setSupplierSystemOrderAirExpressAddReq(supplierSystemOrderAirExpressAddReq);
        // 构建供应商预订-机场快线详细
        List<SupplierSystemOrderAirExpressDetailAddReq> supplierSystemOrderAirExpressDetailAddReqList = new ArrayList<>();
        supplierSystemOrderAirExpressAddReq.setSupplierSystemOrderAirExpressDetailAddReqList(supplierSystemOrderAirExpressDetailAddReqList);
        supplierSystemOrderAirExpressAddReq.setContactName(airportExpressOrder.getContactName());
        supplierSystemOrderAirExpressAddReq.setContactMobileAreaCode(airportExpressOrder.getContactMobileAreaCode());
        supplierSystemOrderAirExpressAddReq.setContactMobile(airportExpressOrder.getContactMobile());
        supplierSystemOrderAirExpressAddReq.setContactEmail(airportExpressOrder.getContactEmail());
        supplierSystemOrderAirExpressAddReq.setCustomerRemark(airportExpressOrder.getRemark());
        StringBuilder adultTicketNumberSb = new StringBuilder("");
        StringBuilder childrenTicketNumberSb = new StringBuilder("");
        for (AirportExpressTicketMTRDTO airportExpressTicketMTRDTO : airportExpressMTRDTO.getTicket()) {
            if (Objects.equals(airportExpressTicketMTRDTO.getProfile(), MTRProfile.ADULT.getCode())) {
                adultTicketNumberSb.append(airportExpressTicketMTRDTO.getTid() + "、");
            } else if (Objects.equals(airportExpressTicketMTRDTO.getProfile(), MTRProfile.CHILDREN.getCode())) {
                childrenTicketNumberSb.append(airportExpressTicketMTRDTO.getTid() + "、");
            }
        }
        BigDecimal total = BigDecimal.ZERO;
        if (adultTicketNumberSb.length() > 0) {
            adultTicketNumberSb.deleteCharAt(adultTicketNumberSb.lastIndexOf("、"));
            Integer adultTicketNumber = airportExpressOrder.getAdultTicketNumber();
            BigDecimal adultPrice = airportExpressInfoDTO.getAdultPrice();
            total = total.add(adultPrice.multiply(new BigDecimal(adultTicketNumber)));

            SupplierSystemOrderAirExpressDetailAddReq supplierSystemOrderAirExpressDetailAddReq = new SupplierSystemOrderAirExpressDetailAddReq();
            supplierSystemOrderAirExpressDetailAddReq.setNumber(adultTicketNumber);
            supplierSystemOrderAirExpressDetailAddReq.setTicketTypeNameCn(airportExpressInfoDTO.getTicketTypeNameCn());
            supplierSystemOrderAirExpressDetailAddReq.setUnitPrice(airportExpressInfoDTO.getAdultPrice());
            supplierSystemOrderAirExpressDetailAddReq.setTicketNumber(adultTicketNumberSb.toString());
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("name", AirExpressTouristType.ADULT.getName());
            supplierSystemOrderAirExpressDetailAddReq.setPassengerJson(jsonObject.toJSONString());
            supplierSystemOrderAirExpressDetailAddReqList.add(supplierSystemOrderAirExpressDetailAddReq);
        }
        if (childrenTicketNumberSb.length() > 0) {
            childrenTicketNumberSb.deleteCharAt(childrenTicketNumberSb.lastIndexOf("、"));
            Integer childrenTicketNumber = airportExpressOrder.getChildrenTicketNumber();
            BigDecimal childrenPrice = airportExpressInfoDTO.getChildrenPrice();
            total = total.add(childrenPrice.multiply(new BigDecimal(childrenTicketNumber)));

            SupplierSystemOrderAirExpressDetailAddReq supplierSystemOrderAirExpressDetailAddReq = new SupplierSystemOrderAirExpressDetailAddReq();
            supplierSystemOrderAirExpressDetailAddReq.setNumber(childrenTicketNumber);
            supplierSystemOrderAirExpressDetailAddReq.setTicketTypeNameCn(airportExpressInfoDTO.getTicketTypeNameCn());
            supplierSystemOrderAirExpressDetailAddReq.setUnitPrice(childrenPrice);
            supplierSystemOrderAirExpressDetailAddReq.setTicketNumber(childrenTicketNumberSb.toString());
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("name", AirExpressTouristType.CHILDREN.getName());
            supplierSystemOrderAirExpressDetailAddReq.setPassengerJson(jsonObject.toJSONString());
            supplierSystemOrderAirExpressDetailAddReqList.add(supplierSystemOrderAirExpressDetailAddReq);
        }
        supplierOrderSystemAirExpressAddReq.setTotalFee(total);
        supplierOrderSystemAirExpressAddReq.setPayableAmount(total);
        return supplierOrderSystemAirExpressAddReq;
    }
}
